-----------------------

Data Exploration & Visualization.

-----------------------

In [1]:
# Data exploration
from pathlib import Path

import os
import seaborn as sns
import matplotlib.pyplot as plt


%matplotlib inline

FOLDER_TRN = Path('train/')

fnames = os.listdir(FOLDER_TRN)
labels = []
for fname in fnames:
    labels.append(fname.split('.')[0])

sns.countplot(labels)
plt.title('Cats vs Dogs');

-----------------------

Dogs & Cats Category Codes In ImageNet.

-----------------------

In [2]:
dogs_code = [
    'n02085620','n02085782','n02085936','n02086079',
    'n02086240','n02086646','n02086910','n02087046',
    'n02087394','n02088094','n02088238','n02088364',
    'n02088466','n02088632','n02089078','n02089867',
    'n02089973','n02090379','n02090622','n02090721',
    'n02091032','n02091134','n02091244','n02091467',
    'n02091635','n02091831','n02092002','n02092339',
    'n02093256','n02093428','n02093647','n02093754',
    'n02093859','n02093991','n02094114','n02094258',
    'n02094433','n02095314','n02095570','n02095889',
    'n02096051','n02096177','n02096294','n02096437',
    'n02096585','n02097047','n02097130','n02097209',
    'n02097298','n02097474','n02097658','n02098105',
    'n02098286','n02098413','n02099267','n02099429',
    'n02099601','n02099712','n02099849','n02100236',
    'n02100583','n02100735','n02100877','n02101006',
    'n02101388','n02101556','n02102040','n02102177',
    'n02102318','n02102480','n02102973','n02104029',
    'n02104365','n02105056','n02105162','n02105251',
    'n02105412','n02105505','n02105641','n02105855',
    'n02106030','n02106166','n02106382','n02106550',
    'n02106662','n02107142','n02107312','n02107574',
    'n02107683','n02107908','n02108000','n02108089',
    'n02108422','n02108551','n02108915','n02109047',
    'n02109525','n02109961','n02110063','n02110185',
    'n02110341','n02110627','n02110806','n02110958',
    'n02111129','n02111277','n02111500','n02111889',
    'n02112018','n02112137','n02112350','n02112706',
    'n02113023','n02113186','n02113624','n02113712',
    'n02113799','n02113978'
]

cats_code = [
    'n02123045','n02123159','n02123394','n02123597',
    'n02124075','n02125311','n02127052'
]

-----------------------------

GPU Resources

-----------------------------

In [3]:
# checkout GPU
!nvidia-smi
Sun Aug 25 03:30:48 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.40.04    Driver Version: 418.40.04    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla K80           On   | 00000000:00:1E.0 Off |                    0 |
| N/A   35C    P8    26W / 149W |      0MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

-----------------------------

Data Cleaning

-----------------------------

In [4]:
# Using pretrained models to find out abnormal images
from keras.preprocessing import image
from keras.applications import Xception, xception, InceptionV3, inception_v3, ResNet50, resnet50, InceptionResNetV2, inception_resnet_v2, \
    NASNetLarge, nasnet

import numpy as np
import tensorflow as tf
import keras.backend.tensorflow_backend as KTF


KTF.set_session(tf.Session(config=tf.ConfigProto(device_count={'gpu':0})))

CF_FOLDER = Path('cheatfiles/')


def find_out_cheat_files(model, preprocess_func, decode, img_size):
    """
        use pretrained model(on imagenet) to find out images that may confuse my model in later training step.
    """
    
    cheat_files = []
    for fname in fnames:
        category = cats_code if fname.split('.')[0] == 'cat' else dogs_code
        img_path = FOLDER_TRN / fname
        img = image.load_img(img_path, target_size=img_size)
        arr = image.img_to_array(img)
        tensor = np.expand_dims(arr, axis=0)
        tensor = preprocess_func(tensor)
        preds = model.predict(tensor)
        preds_decode, _, __ = zip(*decode(preds, top=30)[0])

        if not np.intersect1d(preds_decode, category).size:
            cheat_files.append(fname)
    
    return cheat_files
Using TensorFlow backend.
In [10]:
# Found out by Xception
cheatfiles_xception = find_out_cheat_files(
    model=Xception(weights='imagenet'),
    preprocess_func=xception.preprocess_input,
    decode=xception.decode_predictions,
    img_size=(299, 299)
)
In [14]:
# Record the identification by Xception
np.savez(CF_FOLDER / 'xception_top30.npz', xception=cheatfiles_xception)
In [5]:
cheatfiles_xception = np.load(CF_FOLDER / 'xception_top30.npz')['xception']
In [6]:
len(cheatfiles_xception)
Out[6]:
103
In [16]:
# Found out by inception_v3
cheatfiles_inception_v3 = find_out_cheat_files(
    model=InceptionV3(weights='imagenet'), 
    preprocess_func=inception_v3.preprocess_input, 
    decode=inception_v3.decode_predictions,
    img_size=(299, 299)
)
In [18]:
# Record the identification by InceptionV3
np.savez(CF_FOLDER / 'inception_v3_top30.npz', inception_v3=cheatfiles_inception_v3)
In [6]:
cheatfiles_inception_v3 = np.load(CF_FOLDER / 'inception_v3_top30.npz')['inception_v3']
In [8]:
len(cheatfiles_inception_v3)
Out[8]:
147
In [19]:
# Found out by resnet50
cheatfiles_resnet50 = find_out_cheat_files(
    model=ResNet50(weights='imagenet'), 
    preprocess_func=resnet50.preprocess_input, 
    decode=resnet50.decode_predictions, 
    img_size=(224, 224)
)
In [21]:
# Record the identification by ResNet50
np.savez(CF_FOLDER / 'resnet50_top30.npz', resnet50=cheatfiles_resnet50)
In [7]:
cheatfiles_resnet50 = np.load(CF_FOLDER / 'resnet50_top30.npz')['resnet50']
In [10]:
len(cheatfiles_resnet50)
Out[10]:
325
In [8]:
# Found out by NASNetMobile
cheatfiles_nasnet = find_out_cheat_files(
    model=NASNetLarge(weights='imagenet'), 
    preprocess_func=nasnet.preprocess_input, 
    decode=nasnet.decode_predictions, 
    img_size=(331, 331)
)
WARNING:tensorflow:From /home/ubuntu/anaconda3/envs/tensorflow_p36/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
In [9]:
# Record the identification by NASNetMobile
np.savez(CF_FOLDER / 'nasnet_top30.npz', nasnet=cheatfiles_nasnet)
In [8]:
cheatfiles_nasnet = np.load(CF_FOLDER / 'nasnet_top30.npz')['nasnet']
In [11]:
len(cheatfiles_nasnet)
Out[11]:
96
In [6]:
# Found out by InceptionResNetV2
cheatfiles_inception_resnet_v2 = find_out_cheat_files(
    model=InceptionResNetV2(weights='imagenet'), 
    preprocess_func=inception_resnet_v2.preprocess_input, 
    decode=inception_resnet_v2.decode_predictions, 
    img_size=(299, 299)
)
In [17]:
# Record the identification by InceptionResNet50V2
np.savez(CF_FOLDER / 'inception_resnet_v2_top30.npz', inception_resnet_v2=cheatfiles_inception_resnet_v2)
In [9]:
cheatfiles_inception_resnet_v2 = np.load(CF_FOLDER / 'inception_resnet_v2_top30.npz')['inception_resnet_v2']
In [16]:
len(cheatfiles_inception_resnet_v2)
Out[16]:
124
In [10]:
# Aggregate all the files that found out by above pretrained models
from pprint import pprint
from functools import reduce


cheat_files_by_models = reduce(
    np.union1d, 
    (cheatfiles_xception, cheatfiles_inception_v3, cheatfiles_inception_resnet_v2, cheatfiles_resnet50, cheatfiles_nasnet)
)

print("models found out {} cheat files below:".format(len(cheat_files_by_models)))
pprint(cheat_files_by_models)
models found out 416 cheat files below:
array(['cat.10029.jpg', 'cat.10037.jpg', 'cat.10107.jpg', 'cat.10121.jpg',
       'cat.10209.jpg', 'cat.10220.jpg', 'cat.10266.jpg', 'cat.10270.jpg',
       'cat.10365.jpg', 'cat.10425.jpg', 'cat.10471.jpg', 'cat.10521.jpg',
       'cat.10532.jpg', 'cat.10536.jpg', 'cat.10539.jpg', 'cat.10579.jpg',
       'cat.10609.jpg', 'cat.10634.jpg', 'cat.10636.jpg', 'cat.10700.jpg',
       'cat.10712.jpg', 'cat.10743.jpg', 'cat.10807.jpg', 'cat.10863.jpg',
       'cat.10864.jpg', 'cat.10893.jpg', 'cat.10912.jpg', 'cat.10932.jpg',
       'cat.10946.jpg', 'cat.11018.jpg', 'cat.11039.jpg', 'cat.11062.jpg',
       'cat.11141.jpg', 'cat.11168.jpg', 'cat.11184.jpg', 'cat.11222.jpg',
       'cat.11231.jpg', 'cat.11255.jpg', 'cat.11256.jpg', 'cat.11281.jpg',
       'cat.11297.jpg', 'cat.1139.jpg', 'cat.11399.jpg', 'cat.114.jpg',
       'cat.11432.jpg', 'cat.11544.jpg', 'cat.11562.jpg', 'cat.11565.jpg',
       'cat.11607.jpg', 'cat.11608.jpg', 'cat.11634.jpg', 'cat.11661.jpg',
       'cat.11675.jpg', 'cat.11683.jpg', 'cat.11724.jpg', 'cat.11726.jpg',
       'cat.11777.jpg', 'cat.11823.jpg', 'cat.11870.jpg', 'cat.11879.jpg',
       'cat.11923.jpg', 'cat.11941.jpg', 'cat.11968.jpg', 'cat.11980.jpg',
       'cat.12126.jpg', 'cat.12182.jpg', 'cat.12189.jpg', 'cat.12219.jpg',
       'cat.12222.jpg', 'cat.12227.jpg', 'cat.12239.jpg', 'cat.12252.jpg',
       'cat.12272.jpg', 'cat.12326.jpg', 'cat.12359.jpg', 'cat.12378.jpg',
       'cat.12380.jpg', 'cat.12392.jpg', 'cat.124.jpg', 'cat.12424.jpg',
       'cat.12431.jpg', 'cat.12476.jpg', 'cat.12493.jpg', 'cat.12494.jpg',
       'cat.1277.jpg', 'cat.1361.jpg', 'cat.1380.jpg', 'cat.1423.jpg',
       'cat.1485.jpg', 'cat.1507.jpg', 'cat.1619.jpg', 'cat.1631.jpg',
       'cat.169.jpg', 'cat.1741.jpg', 'cat.1747.jpg', 'cat.1906.jpg',
       'cat.1928.jpg', 'cat.2047.jpg', 'cat.2150.jpg', 'cat.2267.jpg',
       'cat.2279.jpg', 'cat.2337.jpg', 'cat.2355.jpg', 'cat.2384.jpg',
       'cat.2429.jpg', 'cat.2433.jpg', 'cat.245.jpg', 'cat.2456.jpg',
       'cat.2457.jpg', 'cat.2470.jpg', 'cat.2494.jpg', 'cat.2509.jpg',
       'cat.252.jpg', 'cat.2520.jpg', 'cat.2598.jpg', 'cat.2621.jpg',
       'cat.2663.jpg', 'cat.2715.jpg', 'cat.2735.jpg', 'cat.2737.jpg',
       'cat.2748.jpg', 'cat.2817.jpg', 'cat.2835.jpg', 'cat.2845.jpg',
       'cat.2893.jpg', 'cat.2924.jpg', 'cat.2939.jpg', 'cat.2951.jpg',
       'cat.297.jpg', 'cat.3004.jpg', 'cat.3046.jpg', 'cat.3105.jpg',
       'cat.3123.jpg', 'cat.3176.jpg', 'cat.3181.jpg', 'cat.3216.jpg',
       'cat.3219.jpg', 'cat.3250.jpg', 'cat.335.jpg', 'cat.3369.jpg',
       'cat.3399.jpg', 'cat.3410.jpg', 'cat.343.jpg', 'cat.3472.jpg',
       'cat.354.jpg', 'cat.3543.jpg', 'cat.3566.jpg', 'cat.3637.jpg',
       'cat.3658.jpg', 'cat.3672.jpg', 'cat.3699.jpg', 'cat.3713.jpg',
       'cat.372.jpg', 'cat.3731.jpg', 'cat.3738.jpg', 'cat.3766.jpg',
       'cat.3822.jpg', 'cat.3845.jpg', 'cat.3859.jpg', 'cat.3868.jpg',
       'cat.388.jpg', 'cat.3892.jpg', 'cat.4076.jpg', 'cat.4100.jpg',
       'cat.4126.jpg', 'cat.4190.jpg', 'cat.4199.jpg', 'cat.4272.jpg',
       'cat.4308.jpg', 'cat.4338.jpg', 'cat.4360.jpg', 'cat.44.jpg',
       'cat.4432.jpg', 'cat.45.jpg', 'cat.4503.jpg', 'cat.4554.jpg',
       'cat.4575.jpg', 'cat.4688.jpg', 'cat.4786.jpg', 'cat.4807.jpg',
       'cat.4833.jpg', 'cat.4842.jpg', 'cat.4852.jpg', 'cat.4874.jpg',
       'cat.4965.jpg', 'cat.4976.jpg', 'cat.4985.jpg', 'cat.4986.jpg',
       'cat.499.jpg', 'cat.4994.jpg', 'cat.5.jpg', 'cat.503.jpg',
       'cat.5071.jpg', 'cat.5123.jpg', 'cat.5168.jpg', 'cat.5173.jpg',
       'cat.5176.jpg', 'cat.5184.jpg', 'cat.5241.jpg', 'cat.5324.jpg',
       'cat.5347.jpg', 'cat.5351.jpg', 'cat.5355.jpg', 'cat.539.jpg',
       'cat.5418.jpg', 'cat.5435.jpg', 'cat.5446.jpg', 'cat.5465.jpg',
       'cat.5472.jpg', 'cat.5502.jpg', 'cat.5527.jpg', 'cat.5534.jpg',
       'cat.5583.jpg', 'cat.5595.jpg', 'cat.5609.jpg', 'cat.5623.jpg',
       'cat.5712.jpg', 'cat.5733.jpg', 'cat.5773.jpg', 'cat.5795.jpg',
       'cat.5804.jpg', 'cat.5816.jpg', 'cat.5818.jpg', 'cat.5820.jpg',
       'cat.5843.jpg', 'cat.587.jpg', 'cat.5954.jpg', 'cat.5974.jpg',
       'cat.5981.jpg', 'cat.599.jpg', 'cat.6.jpg', 'cat.6017.jpg',
       'cat.6085.jpg', 'cat.6086.jpg', 'cat.6235.jpg', 'cat.6262.jpg',
       'cat.6272.jpg', 'cat.6307.jpg', 'cat.6345.jpg', 'cat.6348.jpg',
       'cat.6402.jpg', 'cat.6429.jpg', 'cat.6442.jpg', 'cat.6451.jpg',
       'cat.6526.jpg', 'cat.6530.jpg', 'cat.6543.jpg', 'cat.6568.jpg',
       'cat.6590.jpg', 'cat.6655.jpg', 'cat.6696.jpg', 'cat.6699.jpg',
       'cat.6703.jpg', 'cat.6734.jpg', 'cat.674.jpg', 'cat.6781.jpg',
       'cat.6868.jpg', 'cat.6900.jpg', 'cat.6906.jpg', 'cat.6915.jpg',
       'cat.6965.jpg', 'cat.7001.jpg', 'cat.7009.jpg', 'cat.704.jpg',
       'cat.7047.jpg', 'cat.712.jpg', 'cat.7194.jpg', 'cat.7206.jpg',
       'cat.724.jpg', 'cat.7263.jpg', 'cat.7281.jpg', 'cat.7291.jpg',
       'cat.7296.jpg', 'cat.7300.jpg', 'cat.7312.jpg', 'cat.7354.jpg',
       'cat.7372.jpg', 'cat.7377.jpg', 'cat.738.jpg', 'cat.7411.jpg',
       'cat.7416.jpg', 'cat.7429.jpg', 'cat.7432.jpg', 'cat.7464.jpg',
       'cat.7487.jpg', 'cat.7493.jpg', 'cat.7526.jpg', 'cat.7545.jpg',
       'cat.7550.jpg', 'cat.7564.jpg', 'cat.7599.jpg', 'cat.7604.jpg',
       'cat.7661.jpg', 'cat.767.jpg', 'cat.7671.jpg', 'cat.7682.jpg',
       'cat.7703.jpg', 'cat.7707.jpg', 'cat.7728.jpg', 'cat.7738.jpg',
       'cat.7758.jpg', 'cat.7897.jpg', 'cat.7899.jpg', 'cat.7919.jpg',
       'cat.7920.jpg', 'cat.796.jpg', 'cat.7964.jpg', 'cat.7968.jpg',
       'cat.8033.jpg', 'cat.8044.jpg', 'cat.8056.jpg', 'cat.8068.jpg',
       'cat.8087.jpg', 'cat.8092.jpg', 'cat.8118.jpg', 'cat.8122.jpg',
       'cat.8138.jpg', 'cat.8200.jpg', 'cat.8289.jpg', 'cat.8369.jpg',
       'cat.8383.jpg', 'cat.8431.jpg', 'cat.8448.jpg', 'cat.8456.jpg',
       'cat.8470.jpg', 'cat.8487.jpg', 'cat.8504.jpg', 'cat.8542.jpg',
       'cat.8576.jpg', 'cat.8647.jpg', 'cat.8657.jpg', 'cat.8675.jpg',
       'cat.8744.jpg', 'cat.8755.jpg', 'cat.8765.jpg', 'cat.8828.jpg',
       'cat.883.jpg', 'cat.8854.jpg', 'cat.8914.jpg', 'cat.8921.jpg',
       'cat.9006.jpg', 'cat.9066.jpg', 'cat.908.jpg', 'cat.9090.jpg',
       'cat.9110.jpg', 'cat.9144.jpg', 'cat.9171.jpg', 'cat.9250.jpg',
       'cat.9277.jpg', 'cat.9288.jpg', 'cat.9290.jpg', 'cat.933.jpg',
       'cat.934.jpg', 'cat.9360.jpg', 'cat.9444.jpg', 'cat.9445.jpg',
       'cat.9456.jpg', 'cat.9458.jpg', 'cat.9494.jpg', 'cat.9499.jpg',
       'cat.9513.jpg', 'cat.9520.jpg', 'cat.9552.jpg', 'cat.9589.jpg',
       'cat.9596.jpg', 'cat.9622.jpg', 'cat.9642.jpg', 'cat.9695.jpg',
       'cat.9836.jpg', 'cat.9882.jpg', 'cat.9925.jpg', 'cat.9947.jpg',
       'cat.9983.jpg', 'cat.9986.jpg', 'cat.9987.jpg', 'dog.10161.jpg',
       'dog.10190.jpg', 'dog.10225.jpg', 'dog.10237.jpg', 'dog.10747.jpg',
       'dog.10801.jpg', 'dog.11266.jpg', 'dog.11299.jpg', 'dog.11437.jpg',
       'dog.1194.jpg', 'dog.12148.jpg', 'dog.12155.jpg', 'dog.12376.jpg',
       'dog.1259.jpg', 'dog.1308.jpg', 'dog.1625.jpg', 'dog.1773.jpg',
       'dog.1895.jpg', 'dog.2339.jpg', 'dog.2422.jpg', 'dog.2614.jpg',
       'dog.3035.jpg', 'dog.3497.jpg', 'dog.3889.jpg', 'dog.4218.jpg',
       'dog.4367.jpg', 'dog.4507.jpg', 'dog.4595.jpg', 'dog.5336.jpg',
       'dog.5604.jpg', 'dog.6028.jpg', 'dog.6413.jpg', 'dog.6475.jpg',
       'dog.6725.jpg', 'dog.7076.jpg', 'dog.729.jpg', 'dog.806.jpg',
       'dog.8736.jpg', 'dog.8898.jpg', 'dog.9188.jpg', 'dog.9517.jpg'],
      dtype='<U13')
In [11]:
# Record the identification by all models
np.savez(CF_FOLDER / 'models_all_top30.npz', all=cheat_files_by_models)
In [5]:
cheat_files_by_models = np.load(CF_FOLDER / 'models_all_top30.npz')['all']
In [6]:
# Abnormal images listed on kaggle discussion forum
import pandas as pd

from pprint import pprint

# The following files listed on discussion forum for reference
df_cheat = pd.read_csv('cheat.csv')
arr_cheat = df_cheat['filename'].values
arr_cheat = [name + '.jpg' for name in arr_cheat if not name.endswith('.jpg')]
print("furthermore, there are {} cheat files collected by discussion forum:".format(len(arr_cheat)))
pprint(arr_cheat)
furthermore, there are 49 cheat files collected by discussion forum:
['dog.11731.jpg',
 'dog.4334.jpg',
 'cat.4688.jpg',
 'cat.11222.jpg',
 'cat.1450.jpg',
 'cat.2159.jpg',
 'cat.3822.jpg',
 'cat.4104.jpg',
 'cat.5355.jpg',
 'cat.7194.jpg',
 'cat.7920.jpg',
 'cat.9250.jpg',
 'cat.9444.jpg',
 'cat.9882.jpg',
 'dog.11538.jpg',
 'dog.11724.jpg',
 'dog.8507.jpg',
 'cat.2939.jpg',
 'cat.3216.jpg',
 'cat.4833.jpg',
 'cat.7968.jpg',
 'cat.8470.jpg',
 'dog.10161.jpg',
 'dog.10190.jpg',
 'dog.11186.jpg',
 'dog.1308.jpg',
 'dog.1895.jpg',
 'dog.9188.jpg',
 'cat.5418.jpg',
 'dog.10747.jpg',
 'dog.2614.jpg',
 'dog.4367.jpg',
 'dog.8736.jpg',
 'cat.7377.jpg',
 'dog.12376.jpg',
 'dog.1773.jpg',
 'cat.10712.jpg',
 'cat.11184.jpg',
 'cat.7564.jpg',
 'cat.8456.jpg',
 'dog.10237.jpg',
 'dog.1043.jpg',
 'dog.1194.jpg',
 'dog.5604.jpg',
 'dog.9517.jpg',
 'cat.11565.jpg',
 'dog.10797.jpg',
 'dog.2877.jpg',
 'dog.8898.jpg']
In [7]:
# Cheat files aggregation
cheatfiles_all = np.union1d(cheat_files_by_models, arr_cheat)
print("From the above, there are {} cheat files in all, as below:".format(len(cheatfiles_all)))
pprint(cheatfiles_all)
From the above, there are 428 cheat files in all, as below:
array(['cat.10029.jpg', 'cat.10037.jpg', 'cat.10107.jpg', 'cat.10121.jpg',
       'cat.10209.jpg', 'cat.10220.jpg', 'cat.10266.jpg', 'cat.10270.jpg',
       'cat.10365.jpg', 'cat.10425.jpg', 'cat.10471.jpg', 'cat.10521.jpg',
       'cat.10532.jpg', 'cat.10536.jpg', 'cat.10539.jpg', 'cat.10579.jpg',
       'cat.10609.jpg', 'cat.10634.jpg', 'cat.10636.jpg', 'cat.10700.jpg',
       'cat.10712.jpg', 'cat.10743.jpg', 'cat.10807.jpg', 'cat.10863.jpg',
       'cat.10864.jpg', 'cat.10893.jpg', 'cat.10912.jpg', 'cat.10932.jpg',
       'cat.10946.jpg', 'cat.11018.jpg', 'cat.11039.jpg', 'cat.11062.jpg',
       'cat.11141.jpg', 'cat.11168.jpg', 'cat.11184.jpg', 'cat.11222.jpg',
       'cat.11231.jpg', 'cat.11255.jpg', 'cat.11256.jpg', 'cat.11281.jpg',
       'cat.11297.jpg', 'cat.1139.jpg', 'cat.11399.jpg', 'cat.114.jpg',
       'cat.11432.jpg', 'cat.11544.jpg', 'cat.11562.jpg', 'cat.11565.jpg',
       'cat.11607.jpg', 'cat.11608.jpg', 'cat.11634.jpg', 'cat.11661.jpg',
       'cat.11675.jpg', 'cat.11683.jpg', 'cat.11724.jpg', 'cat.11726.jpg',
       'cat.11777.jpg', 'cat.11823.jpg', 'cat.11870.jpg', 'cat.11879.jpg',
       'cat.11923.jpg', 'cat.11941.jpg', 'cat.11968.jpg', 'cat.11980.jpg',
       'cat.12126.jpg', 'cat.12182.jpg', 'cat.12189.jpg', 'cat.12219.jpg',
       'cat.12222.jpg', 'cat.12227.jpg', 'cat.12239.jpg', 'cat.12252.jpg',
       'cat.12272.jpg', 'cat.12326.jpg', 'cat.12359.jpg', 'cat.12378.jpg',
       'cat.12380.jpg', 'cat.12392.jpg', 'cat.124.jpg', 'cat.12424.jpg',
       'cat.12431.jpg', 'cat.12476.jpg', 'cat.12493.jpg', 'cat.12494.jpg',
       'cat.1277.jpg', 'cat.1361.jpg', 'cat.1380.jpg', 'cat.1423.jpg',
       'cat.1450.jpg', 'cat.1485.jpg', 'cat.1507.jpg', 'cat.1619.jpg',
       'cat.1631.jpg', 'cat.169.jpg', 'cat.1741.jpg', 'cat.1747.jpg',
       'cat.1906.jpg', 'cat.1928.jpg', 'cat.2047.jpg', 'cat.2150.jpg',
       'cat.2159.jpg', 'cat.2267.jpg', 'cat.2279.jpg', 'cat.2337.jpg',
       'cat.2355.jpg', 'cat.2384.jpg', 'cat.2429.jpg', 'cat.2433.jpg',
       'cat.245.jpg', 'cat.2456.jpg', 'cat.2457.jpg', 'cat.2470.jpg',
       'cat.2494.jpg', 'cat.2509.jpg', 'cat.252.jpg', 'cat.2520.jpg',
       'cat.2598.jpg', 'cat.2621.jpg', 'cat.2663.jpg', 'cat.2715.jpg',
       'cat.2735.jpg', 'cat.2737.jpg', 'cat.2748.jpg', 'cat.2817.jpg',
       'cat.2835.jpg', 'cat.2845.jpg', 'cat.2893.jpg', 'cat.2924.jpg',
       'cat.2939.jpg', 'cat.2951.jpg', 'cat.297.jpg', 'cat.3004.jpg',
       'cat.3046.jpg', 'cat.3105.jpg', 'cat.3123.jpg', 'cat.3176.jpg',
       'cat.3181.jpg', 'cat.3216.jpg', 'cat.3219.jpg', 'cat.3250.jpg',
       'cat.335.jpg', 'cat.3369.jpg', 'cat.3399.jpg', 'cat.3410.jpg',
       'cat.343.jpg', 'cat.3472.jpg', 'cat.354.jpg', 'cat.3543.jpg',
       'cat.3566.jpg', 'cat.3637.jpg', 'cat.3658.jpg', 'cat.3672.jpg',
       'cat.3699.jpg', 'cat.3713.jpg', 'cat.372.jpg', 'cat.3731.jpg',
       'cat.3738.jpg', 'cat.3766.jpg', 'cat.3822.jpg', 'cat.3845.jpg',
       'cat.3859.jpg', 'cat.3868.jpg', 'cat.388.jpg', 'cat.3892.jpg',
       'cat.4076.jpg', 'cat.4100.jpg', 'cat.4104.jpg', 'cat.4126.jpg',
       'cat.4190.jpg', 'cat.4199.jpg', 'cat.4272.jpg', 'cat.4308.jpg',
       'cat.4338.jpg', 'cat.4360.jpg', 'cat.44.jpg', 'cat.4432.jpg',
       'cat.45.jpg', 'cat.4503.jpg', 'cat.4554.jpg', 'cat.4575.jpg',
       'cat.4688.jpg', 'cat.4786.jpg', 'cat.4807.jpg', 'cat.4833.jpg',
       'cat.4842.jpg', 'cat.4852.jpg', 'cat.4874.jpg', 'cat.4965.jpg',
       'cat.4976.jpg', 'cat.4985.jpg', 'cat.4986.jpg', 'cat.499.jpg',
       'cat.4994.jpg', 'cat.5.jpg', 'cat.503.jpg', 'cat.5071.jpg',
       'cat.5123.jpg', 'cat.5168.jpg', 'cat.5173.jpg', 'cat.5176.jpg',
       'cat.5184.jpg', 'cat.5241.jpg', 'cat.5324.jpg', 'cat.5347.jpg',
       'cat.5351.jpg', 'cat.5355.jpg', 'cat.539.jpg', 'cat.5418.jpg',
       'cat.5435.jpg', 'cat.5446.jpg', 'cat.5465.jpg', 'cat.5472.jpg',
       'cat.5502.jpg', 'cat.5527.jpg', 'cat.5534.jpg', 'cat.5583.jpg',
       'cat.5595.jpg', 'cat.5609.jpg', 'cat.5623.jpg', 'cat.5712.jpg',
       'cat.5733.jpg', 'cat.5773.jpg', 'cat.5795.jpg', 'cat.5804.jpg',
       'cat.5816.jpg', 'cat.5818.jpg', 'cat.5820.jpg', 'cat.5843.jpg',
       'cat.587.jpg', 'cat.5954.jpg', 'cat.5974.jpg', 'cat.5981.jpg',
       'cat.599.jpg', 'cat.6.jpg', 'cat.6017.jpg', 'cat.6085.jpg',
       'cat.6086.jpg', 'cat.6235.jpg', 'cat.6262.jpg', 'cat.6272.jpg',
       'cat.6307.jpg', 'cat.6345.jpg', 'cat.6348.jpg', 'cat.6402.jpg',
       'cat.6429.jpg', 'cat.6442.jpg', 'cat.6451.jpg', 'cat.6526.jpg',
       'cat.6530.jpg', 'cat.6543.jpg', 'cat.6568.jpg', 'cat.6590.jpg',
       'cat.6655.jpg', 'cat.6696.jpg', 'cat.6699.jpg', 'cat.6703.jpg',
       'cat.6734.jpg', 'cat.674.jpg', 'cat.6781.jpg', 'cat.6868.jpg',
       'cat.6900.jpg', 'cat.6906.jpg', 'cat.6915.jpg', 'cat.6965.jpg',
       'cat.7001.jpg', 'cat.7009.jpg', 'cat.704.jpg', 'cat.7047.jpg',
       'cat.712.jpg', 'cat.7194.jpg', 'cat.7206.jpg', 'cat.724.jpg',
       'cat.7263.jpg', 'cat.7281.jpg', 'cat.7291.jpg', 'cat.7296.jpg',
       'cat.7300.jpg', 'cat.7312.jpg', 'cat.7354.jpg', 'cat.7372.jpg',
       'cat.7377.jpg', 'cat.738.jpg', 'cat.7411.jpg', 'cat.7416.jpg',
       'cat.7429.jpg', 'cat.7432.jpg', 'cat.7464.jpg', 'cat.7487.jpg',
       'cat.7493.jpg', 'cat.7526.jpg', 'cat.7545.jpg', 'cat.7550.jpg',
       'cat.7564.jpg', 'cat.7599.jpg', 'cat.7604.jpg', 'cat.7661.jpg',
       'cat.767.jpg', 'cat.7671.jpg', 'cat.7682.jpg', 'cat.7703.jpg',
       'cat.7707.jpg', 'cat.7728.jpg', 'cat.7738.jpg', 'cat.7758.jpg',
       'cat.7897.jpg', 'cat.7899.jpg', 'cat.7919.jpg', 'cat.7920.jpg',
       'cat.796.jpg', 'cat.7964.jpg', 'cat.7968.jpg', 'cat.8033.jpg',
       'cat.8044.jpg', 'cat.8056.jpg', 'cat.8068.jpg', 'cat.8087.jpg',
       'cat.8092.jpg', 'cat.8118.jpg', 'cat.8122.jpg', 'cat.8138.jpg',
       'cat.8200.jpg', 'cat.8289.jpg', 'cat.8369.jpg', 'cat.8383.jpg',
       'cat.8431.jpg', 'cat.8448.jpg', 'cat.8456.jpg', 'cat.8470.jpg',
       'cat.8487.jpg', 'cat.8504.jpg', 'cat.8542.jpg', 'cat.8576.jpg',
       'cat.8647.jpg', 'cat.8657.jpg', 'cat.8675.jpg', 'cat.8744.jpg',
       'cat.8755.jpg', 'cat.8765.jpg', 'cat.8828.jpg', 'cat.883.jpg',
       'cat.8854.jpg', 'cat.8914.jpg', 'cat.8921.jpg', 'cat.9006.jpg',
       'cat.9066.jpg', 'cat.908.jpg', 'cat.9090.jpg', 'cat.9110.jpg',
       'cat.9144.jpg', 'cat.9171.jpg', 'cat.9250.jpg', 'cat.9277.jpg',
       'cat.9288.jpg', 'cat.9290.jpg', 'cat.933.jpg', 'cat.934.jpg',
       'cat.9360.jpg', 'cat.9444.jpg', 'cat.9445.jpg', 'cat.9456.jpg',
       'cat.9458.jpg', 'cat.9494.jpg', 'cat.9499.jpg', 'cat.9513.jpg',
       'cat.9520.jpg', 'cat.9552.jpg', 'cat.9589.jpg', 'cat.9596.jpg',
       'cat.9622.jpg', 'cat.9642.jpg', 'cat.9695.jpg', 'cat.9836.jpg',
       'cat.9882.jpg', 'cat.9925.jpg', 'cat.9947.jpg', 'cat.9983.jpg',
       'cat.9986.jpg', 'cat.9987.jpg', 'dog.10161.jpg', 'dog.10190.jpg',
       'dog.10225.jpg', 'dog.10237.jpg', 'dog.1043.jpg', 'dog.10747.jpg',
       'dog.10797.jpg', 'dog.10801.jpg', 'dog.11186.jpg', 'dog.11266.jpg',
       'dog.11299.jpg', 'dog.11437.jpg', 'dog.11538.jpg', 'dog.11724.jpg',
       'dog.11731.jpg', 'dog.1194.jpg', 'dog.12148.jpg', 'dog.12155.jpg',
       'dog.12376.jpg', 'dog.1259.jpg', 'dog.1308.jpg', 'dog.1625.jpg',
       'dog.1773.jpg', 'dog.1895.jpg', 'dog.2339.jpg', 'dog.2422.jpg',
       'dog.2614.jpg', 'dog.2877.jpg', 'dog.3035.jpg', 'dog.3497.jpg',
       'dog.3889.jpg', 'dog.4218.jpg', 'dog.4334.jpg', 'dog.4367.jpg',
       'dog.4507.jpg', 'dog.4595.jpg', 'dog.5336.jpg', 'dog.5604.jpg',
       'dog.6028.jpg', 'dog.6413.jpg', 'dog.6475.jpg', 'dog.6725.jpg',
       'dog.7076.jpg', 'dog.729.jpg', 'dog.806.jpg', 'dog.8507.jpg',
       'dog.8736.jpg', 'dog.8898.jpg', 'dog.9188.jpg', 'dog.9517.jpg'],
      dtype='<U13')

-----------------------

Dirty Data Visualization

-----------------------

In [13]:
# Function that let us see some abnormal images
def view_of_cheat_files(nrows, ncols, start, end):
    if abs(end - start) > nrows * ncols:
        raise IndexError("index out of range!")
    
    fig, ax = plt.subplots(nrows, ncols, figsize=(25, 25))
    plt.subplots_adjust(hspace=.9)

    for num in range(start, end):
        file_name = cheatfiles_all[num]
        file_path = FOLDER_TRN / cheatfiles_all[num]
        label = file_name.split('.')[0]
        img = plt.imread(file_path)
    
        ax[num // ncols, num % ncols].imshow(img)
        ax[num // ncols, num % ncols].set_title("file: {}\n label: {}".format(file_name, label), size=12)
        ax[num // ncols, num % ncols].get_xaxis().set_visible(False)
        ax[num // ncols, num % ncols].get_yaxis().set_visible(False)
In [23]:
# view of the top 64 abnormal images
view_of_cheat_files(8, 8, 0, 64)
In [24]:
# view of the last 64 abnormal images
view_of_cheat_files(8, 8, -64, 0)

-----------------------

Dirty Data Removing

-----------------------

In [8]:
# Remove above cheat files & bulid a dataframe
for file in cheatfiles_all:
    fnames.remove(file)

df = pd.DataFrame({
    'file': fnames,
    'label': [name.split('.')[0] for name in fnames]
})
df.head()
Out[8]:
file label
0 cat.2960.jpg cat
1 dog.11107.jpg dog
2 cat.3056.jpg cat
3 cat.12279.jpg cat
4 dog.7786.jpg dog
In [26]:
# Save as csv file
df.to_csv('data_clean.csv', index=False)

Training Set & Validation Set

In [5]:
df = pd.read_csv('data_clean.csv')
df.head()
Out[5]:
file label
0 cat.2960.jpg cat
1 dog.11107.jpg dog
2 cat.3056.jpg cat
3 cat.12279.jpg cat
4 dog.7786.jpg dog
In [10]:
from sklearn.model_selection import train_test_split


# Dataframe of training set & validation set
df_trn, df_val = train_test_split(df, stratify=df['label'], random_state=0)
df_trn.reset_index(drop=True, inplace=True)
df_val.reset_index(drop=True, inplace=True)
In [11]:
def show_images_from_df(data_df, nrows, ncols, directory=FOLDER_TRN, is_train=True, pred_label=None):
    """
        showing images from dataframe.
    """
    
    fig, ax = plt.subplots(nrows, ncols, figsize=(15, 15))
    plt.subplots_adjust(wspace=.4, hspace=.5)
    
    for idx, row in data_df[:nrows*ncols].iterrows():
        fname = row['file']
        prob = pred_label[idx] if not is_train else 1.000
        label = row['label'] if is_train  else ('dog' if prob > 0.500 else 'cat')
        img = plt.imread(os.path.join(directory, fname))
        
        ax[idx // ncols, idx % ncols].imshow(img)
        if is_train:
            ax[idx // ncols, idx % ncols].set_title("file: {}\n label: {}".format(fname, label), size=12)
        else:
            ax[idx // ncols, idx % ncols].set_title("file: {}\n prediction: {}\nprobability:{:.3f}".format(fname, label, prob), size=12)

        ax[idx // ncols, idx % ncols].get_xaxis().set_visible(False)
        ax[idx // ncols, idx % ncols].get_yaxis().set_visible(False)
In [30]:
# Show images of training data
show_images_from_df(df_trn, 5, 5)
In [31]:
# Show images of validation data
show_images_from_df(df_val, 5, 5)

Data Augmentation

In [12]:
from keras.preprocessing.image import ImageDataGenerator


# Batch size
BATCH_SIZE_331 = 16
BATCH_SIZE_299 = 32

# Image size
SIZE_299 = (299, 299)
SIZE_331 = (331, 331)

def generator_flow(
    datagen, df, target_size, batch_size,
    directory=FOLDER_TRN, x_col='file', y_col='label',
    mode='binary', shuffle=True
):
    gen = datagen.flow_from_dataframe(
        df, 
        directory=directory, 
        x_col=x_col,
        y_col=y_col, 
        target_size=target_size, 
        class_mode=mode,
        batch_size=batch_size,
        shuffle=shuffle
    )
    return gen

datagen_trn = ImageDataGenerator(
    rotation_range=25,
    
    width_shift_range=.1,
    height_shift_range=.1,
    zoom_range=.2,
    shear_range=.1,
    horizontal_flip=True
)
datagen_val = ImageDataGenerator()
In [13]:
# Data generator of training data & validation data with different size
generator_trn_331 = generator_flow(datagen_trn, df_trn, SIZE_331, BATCH_SIZE_331)
generator_val_331 = generator_flow(datagen_val, df_val, SIZE_331, BATCH_SIZE_331)
generator_trn_299 = generator_flow(datagen_trn, df_trn, SIZE_299, BATCH_SIZE_299)
generator_val_299 = generator_flow(datagen_val, df_val, SIZE_299, BATCH_SIZE_299)
Found 18429 images belonging to 2 classes.
Found 6143 images belonging to 2 classes.
Found 18429 images belonging to 2 classes.
Found 6143 images belonging to 2 classes.
In [83]:
# Class indices
print(generator_trn_331.class_indices)
print(generator_trn_299.class_indices)
print(generator_val_331.class_indices)
print(generator_val_299.class_indices)
{'cat': 0, 'dog': 1}
{'cat': 0, 'dog': 1}
{'cat': 0, 'dog': 1}
{'cat': 0, 'dog': 1}
In [14]:
# define a function for sorting the testing images in their directory by number in image name
import re


def key_func(entry):
    """
        sort files in their directory by number of its name.
    """
    return int(re.search(r'\d+', entry).group())
In [15]:
# Sort testing data
FOLDER_TEST = Path('test/')

fnames_tst = os.listdir(FOLDER_TEST)
fnames_tst.sort(key=key_func)
fnames_tst[:10]
Out[15]:
['1.jpg',
 '2.jpg',
 '3.jpg',
 '4.jpg',
 '5.jpg',
 '6.jpg',
 '7.jpg',
 '8.jpg',
 '9.jpg',
 '10.jpg']
In [16]:
# Generator for testing data, set 'shuffle'=False
df_tst = pd.DataFrame({
    'file': fnames_tst
})
datagen_tst = ImageDataGenerator()
generator_tst_331 = generator_flow(datagen_tst, df_tst, (331, 331), 16, directory=FOLDER_TEST, y_col=None, mode=None, shuffle=False)
generator_tst_299 = generator_flow(datagen_tst, df_tst, SIZE_299, BATCH_SIZE_299, directory=FOLDER_TEST, y_col=None, mode=None, shuffle=False)
Found 12500 images.
Found 12500 images.